package com.agileboot.common.utils.poi;

import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode.Internal;
import com.agileboot.common.utils.file.FileTypeUtil;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

/**
 * 通用数据导入导出服务
 *
 * @author agileboot
 */
@Slf4j
@Service
public class ExportImportService {

    /**
     * 通用导出方法
     *
     * @param list          数据列表
     * @param clazz         数据类型
     * @param response      HTTP响应对象
     * @param <T>           数据类型
     * @param fileName      文件名
     * @param fileExtension 文件扩展名 (excel/csv)
     */
    public <T> void export(List<T> list, Class<T> clazz, HttpServletResponse response,
            String fileName, String fileExtension) {
        if (list == null || list.isEmpty()) {
            throw new ApiException(Internal.EMPTY_LIST);
        }

        try {
            prepareResponse(response, fileName, fileExtension);

            // 根据文件类型选择导出方式
            if ("csv".equalsIgnoreCase(fileExtension)) {
                CsvUtil.writeToResponse(list, clazz, response);
            } else {
                // 默认使用Excel导出
                CustomExcelUtil.writeToResponse(list, clazz, response);
            }
        } catch (Exception e) {
            log.error("导出数据失败", e);
            throw new ApiException(e, Internal.EXCEL_PROCESS_ERROR, e.getMessage());
        }
    }
    
    /**
     * 导出Excel
     *
     * @param list     数据列表
     * @param clazz    数据类型
     * @param response HTTP响应对象
     * @param fileName 文件名
     * @param <T>      数据类型
     */
    public <T> void exportExcel(List<T> list, Class<T> clazz, HttpServletResponse response, String fileName) {
        export(list, clazz, response, fileName, "excel");
    }
    
    /**
     * 导出CSV
     *
     * @param list     数据列表
     * @param clazz    数据类型
     * @param response HTTP响应对象
     * @param fileName 文件名
     * @param <T>      数据类型
     */
    public <T> void exportCsv(List<T> list, Class<T> clazz, HttpServletResponse response, String fileName) {
        export(list, clazz, response, fileName, "csv");
    }

    /**
     * 通用导入方法
     *
     * @param file  上传的文件
     * @param clazz 目标类型
     * @param <T>   数据类型
     * @return 导入的数据列表
     */
    public <T> List<T> importData(MultipartFile file, Class<T> clazz) {
        if (file == null || file.isEmpty()) {
            throw new ApiException(Internal.EMPTY_FILE);
        }

        // 检查文件类型
        if (FileTypeUtil.isExcel(file)) {
            return CustomExcelUtil.readFromRequest(clazz, file);
        } else if (FileTypeUtil.isCsv(file)) {
            return CsvUtil.readFromRequest(clazz, file);
        } else {
            throw new ApiException(Internal.INVALID_FILE_TYPE);
        }
    }
    
    /**
     * 导入Excel
     *
     * @param file  上传的Excel文件
     * @param clazz 目标类型
     * @param <T>   数据类型
     * @return 导入的数据列表
     */
    public <T> List<T> importExcel(MultipartFile file, Class<T> clazz) {
        if (file == null || file.isEmpty()) {
            throw new ApiException(Internal.EMPTY_FILE);
        }
        
        if (!FileTypeUtil.isExcel(file)) {
            throw new ApiException(Internal.INVALID_FILE_TYPE, "仅支持Excel文件");
        }
        
        return CustomExcelUtil.readFromRequest(clazz, file);
    }
    
    /**
     * 导入CSV
     *
     * @param file  上传的CSV文件
     * @param clazz 目标类型
     * @param <T>   数据类型
     * @return 导入的数据列表
     */
    public <T> List<T> importCsv(MultipartFile file, Class<T> clazz) {
        if (file == null || file.isEmpty()) {
            throw new ApiException(Internal.EMPTY_FILE);
        }
        
        if (!FileTypeUtil.isCsv(file)) {
            throw new ApiException(Internal.INVALID_FILE_TYPE, "仅支持CSV文件");
        }
        
        return CsvUtil.readFromRequest(clazz, file);
    }

    /**
     * 准备HTTP响应
     *
     * @param response      HTTP响应对象
     * @param fileName      文件名
     * @param fileExtension 文件扩展名
     * @throws IOException IO异常
     */
    private void prepareResponse(HttpServletResponse response, String fileName, String fileExtension)
            throws IOException {
        String encodedFileName = java.net.URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");

        // 设置文件类型和头信息
        if ("csv".equalsIgnoreCase(fileExtension)) {
            response.setContentType("text/csv;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + encodedFileName + ".csv");
        } else {
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + encodedFileName + ".xlsx");
        }

        // 设置通用头信息
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Expires", "0");
    }

    /**
     * 获取导入模板
     *
     * @param clazz         模板类型
     * @param response      HTTP响应对象
     * @param <T>           模板类型
     * @param templateName  模板名称
     * @param fileExtension 文件扩展名
     */
    public <T> void getImportTemplate(Class<T> clazz, HttpServletResponse response,
            String templateName, String fileExtension) {
        try {
            // 创建一个空对象实例用于生成模板
            List<T> templateList = java.util.Collections.singletonList(clazz.newInstance());

            // 准备文件名
            String fileName = StringUtils.isNotBlank(templateName) ? templateName : clazz.getSimpleName() + "导入模板";

            // 导出模板
            export(templateList, clazz, response, fileName, fileExtension);
        } catch (Exception e) {
            log.error("生成导入模板失败", e);
            throw new ApiException(e, Internal.EXCEL_PROCESS_ERROR, e.getMessage());
        }
    }
    
    /**
     * 生成Excel导入模板
     *
     * @param clazz        模板类型
     * @param response     HTTP响应对象
     * @param templateName 模板名称
     * @param <T>          模板类型
     */
    public <T> void exportTemplateExcel(Class<T> clazz, HttpServletResponse response, String templateName) {
        getImportTemplate(clazz, response, templateName, "excel");
    }
    
    /**
     * 生成CSV导入模板
     *
     * @param clazz        模板类型
     * @param response     HTTP响应对象
     * @param templateName 模板名称
     * @param <T>          模板类型
     */
    public <T> void exportTemplateCsv(Class<T> clazz, HttpServletResponse response, String templateName) {
        getImportTemplate(clazz, response, templateName, "csv");
    }
} 